

static const unsigned int LEAF_GENERATOR = 0;
static const unsigned int LEAF_MAIN		 = 1;
static const unsigned int LEAF_SIDE      = 2;


static const float y_min = 2.95f;
static const float y_range = 1.0f;
static const float r = 0.15f;

struct Leaf
{
	float4	pos		: POSITION;
	uint	type	: TYPE;
	float  length : LENGTH;
	float  interval : INTERVAL;
	uint	id		: ID;
};


struct FireParticle
{
	float4 position		:	POSITION;
	float4 direction	:	DIRECTION; 
	float4	params		:	PARAMETERS;	// emitter : .X: ID, .Y: active: Z: age .W: unique ID (0,1,2,...)
										// particle: .X: age .Y: alpha   Z:     .W: type
};


Texture2D	texNoise;
uint		iGlobalID;

DepthStencilState disabled
{
	DepthEnable = false;
	DepthWriteMask = false;
};



///==============================================================================================================================
///---------------- LEAVES   G E O M E T R Y   S O -----------------------------------------------------------------------------------------------


Leaf Leaves_VS(Leaf vin)
{
	return vin;
}


///==============================================================================================================================
///---------------- LEAVES     SO       U   P  D   A   T   E -----------------------------------------------------------------------------------------------


[maxvertexcount(10)]
void GS_SO(point Leaf gin[1], inout PointStream<FireParticle> gsout)
{
	Leaf leaf;
	leaf = gin[0];
	

	if (gin[0].type == LEAF_MAIN) 
	{
		float max_slope = 1.0f;
		float min_slope = 0.01f;

		// y of the main leaf in [0,1] range (depending on height min,max)
		float height_norm = (leaf.pos.y - y_min) / y_range; // [0,1]
		
		// compute alpha for -(a*x)^2 which describes the main leaf shape
		float alpha = max_slope - (max_slope - min_slope) * height_norm; // [max_slope, min_slope]


		float3 p0 = gin[0].pos.xyz;


		const int samples = 5;
		float lengths[samples] = { 0.2f, 0.5f, 0.65f, 0.9f, 1.0f };


		for (int i=0; i<samples; i++)
		{
			float l = lengths[i];

			// h = -(a*l)^2
			float h = -alpha * l * l;
		
			float3 dir = normalize(float3(gin[0].pos.x, 0, gin[0].pos.z));

			leaf.pos.xyz = p0 + float3(dir.x * l, h, dir.z * l);

			//////////////////////

			// f(x) = -(ax)^2 => f'(x) = -2*a^2 * x
			float dL = -2.0f * alpha * alpha * l;

			float3 tangent = normalize(float3(dir.x, dL, dir.z));
			float3 right = cross(float3(0,1,0), tangent);
			float3 up = cross(tangent, right);

			float l_size = 0.09f; /* 0.05f*/


			float3 cntPoint = p0 ;
			leaf.pos.xz -= cntPoint.xz;

			////////////////////////

			FireParticle ps;
			ps.position = float4(leaf.pos.xyz, 1.0f); 
			ps.direction = float4(up,0);
			// id for LEAF_MAIN particles is from 0 to 31, emitters id
			// will be that plus the 'base' id provided by the FireSystem class
			ps.params = float4(iGlobalID + leaf.id, 0,0,0);
			gsout.Append(ps);
		}
	}

}



GeometryShader pGS = CompileShader(gs_4_0, GS_SO());

GeometryShader gsStreamOut = 
			ConstructGSWithSO( 
								pGS, 
								"POSITION.xyzw; DIRECTION.xyzw; PARAMETERS.xyzw"
							);


technique10 LeavesEmitters
{
	pass P0
	{
		SetVertexShader( CompileShader ( vs_4_0, Leaves_VS() ) );
		SetGeometryShader( gsStreamOut );
		SetPixelShader ( NULL);

		SetDepthStencilState(disabled, 0);
	}
}
